﻿
#region Usings
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive.Linq;
using System.Reflection;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
#endregion

namespace FasterWPF
{
    public static partial class CommonExt
    {
        #region Sort and Filter Methods

        //ALSO - add overload methods for Sort passing in an IComparer or IEquitableComparer?!?

        public enum SortOrder
        {
            Asc,
            Desc
        }

        public enum SortControlType
        {
            TextBlock = 0,
            Label = 1,
            TextBox = 2
        }

        public enum SortDataType
        {
            String = 0,
            DateTime = 2,
            Decimal = 3,
            Integer = 4
        }

        public interface ISortArgs
        {
            SortDataType SortDataType
            {
                get;
                set;
            }

            SortDataType SortDataType2
            {
                get;
                set;
            }
        }

        /// <summary>
        /// Sort Composites based on the TextBlock or Label at a specific row-column position within a Composite. If there is no TextBlock or Label, it just tacks the Composite on at the end.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="row"></param>
        /// <param name="column"></param>
        /// <param name="sortOrder"></param>
        /// <param name="controlType"></param>
        /// <returns></returns>
        public static T SortByText<T>(this T chain, int row, int column, SortOrder sortOrder, SortControlType controlType)
               where T : FrameworkElement
        {
            IParent parent = chain.GetSetting<T, IParent>("IParent");

            if (parent is ICanSort)
            {
                ((ICanSort)parent).BeforeSortCollection<T>(chain, null, row, column, sortOrder, controlType);
                ((ICanSort)parent).AfterSortCollection<T>(chain);
            }

            return chain;
        }

        /// <summary>
        /// Sort Composites based on the TextBlock or Label at a specific row-column position within a Composite. Args typically implements FasterWPF.CommonExt.ISortArgs. If there is no TextBlock or Label, it just tacks the Composite on at the end.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="args"></param>
        /// <param name="row"></param>
        /// <param name="column"></param>
        /// <param name="sortOrder"></param>
        /// <param name="controlType"></param>
        /// <returns></returns>
        public static T SortByText<T>(this T chain, object args, int row, int column, SortOrder sortOrder, SortControlType controlType)
               where T : FrameworkElement
        {
            IParent parent = chain.GetSetting<T, IParent>("IParent");

            if (parent is ICanSort)
            {
                ((ICanSort)parent).BeforeSortCollection<T>(chain, args, row, column, sortOrder, controlType);
                ((ICanSort)parent).AfterSortCollection<T>(chain);
            }
            return chain;
        }

        /// <summary>
        ///Sort Composites based on the TextBlock or Label at a specific row-column position within a Composite, and then by a 2nd position. If there is no TextBlock or Label, it treats the position as an Empty String.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="row"></param>
        /// <param name="column"></param>
        /// <param name="row2"></param>
        /// <param name="column2"></param>
        /// <param name="sortOrder"></param>
        /// <param name="sortOrder2"></param>
        /// <param name="sortControlType"></param>
        /// <returns></returns>
        public static T SortByText1AndThenBy2<T>(this T chain, int row, int column, int row2, int column2, SortOrder sortOrder, SortOrder sortOrder2, CommonExt.SortControlType sortControlType)
               where T : FrameworkElement
        {
            IParent parent = chain.GetSetting<T, IParent>("IParent");
            if (parent is ICanSort)
            {
                ((ICanSort)parent).BeforeSortCollection1Then2<T>(chain, null, row, column, row2, column2, sortOrder, sortOrder2, sortControlType);
                ((ICanSort)parent).AfterSortCollection<T>(chain);
            }

            return chain;
        }

        /// <summary>
        /// Sort Composites based on the TextBlock or Label at a specific row-column position within a Composite, and then by a 2nd position. Args typically implements FasterWPF.CommonExt.ISortArgs. If there is no TextBlock or Label, it treats the position as a default null value based on data type.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="args"></param>
        /// <param name="row"></param>
        /// <param name="column"></param>
        /// <param name="row2"></param>
        /// <param name="column2"></param>
        /// <param name="sortOrder"></param>
        /// <param name="sortOrder2"></param>
        /// <param name="sortControlType"></param>
        /// <returns></returns>
        public static T SortByText1AndThenBy2<T>(this T chain, object args, int row, int column, int row2, int column2, SortOrder sortOrder, SortOrder sortOrder2, CommonExt.SortControlType sortControlType)
               where T : FrameworkElement
        {
            IParent parent = chain.GetSetting<T, IParent>("IParent");

            if (parent is ICanSort)
            {
                ((ICanSort)parent).BeforeSortCollection1Then2<T>(chain, args, row, column, row2, column2, sortOrder, sortOrder2, sortControlType);
                ((ICanSort)parent).AfterSortCollection<T>(chain);
            }

            return chain;
        }

        /// <summary>
        /// Filter the items in the ListBox based on the text at a specific row-column position within an item
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="row"></param>
        /// <param name="column"></param>
        /// <param name="filterPredicate"></param>
        /// <returns></returns>
        public static T FilterByText<T>(this T chain, int row, int column, Predicate<string> filterPredicate)
               where T : FrameworkElement
        {
            IParent parent = chain.GetSetting<T, IParent>("IParent");
            if (parent is ICanFilter)
            {
                ((ICanFilter)parent).FilterByText<T>(chain, row, column, filterPredicate);
            }

            return chain;
        }

        /// <summary>
        /// Filter the items in the ListBox based on the text at two specific row-column positions within an item
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="row"></param>
        /// <param name="column"></param>
        /// <param name="row2"></param>
        /// <param name="column2"></param>
        /// <param name="filterPredicate"></param>
        /// <returns></returns>
        public static T FilterByText1And2<T>(this T chain, int row, int column, int row2, int column2, Predicate<Tuple<string, string>> filterPredicate)
               where T : FrameworkElement
        {
            IParent parent = chain.GetSetting<T, IParent>("IParent");
            if (parent is ICanFilter)
            {
                ((ICanFilter)parent).FilterByText1And2<T>(chain, row, column, row2, column2, filterPredicate);
            }

            return chain;
        }

        /// <summary>
        /// Filter the items in the ListBox based on the text at three specific row-column positions within an item
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="row"></param>
        /// <param name="column"></param>
        /// <param name="row2"></param>
        /// <param name="column2"></param>
        /// <param name="row3"></param>
        /// <param name="column3"></param>
        /// <param name="filterPredicate"></param>
        /// <returns></returns>
        public static T FilterByText1And2And3<T>(this T chain, int row, int column, int row2, int column2, int row3, int column3, Predicate<Tuple<string, string, string>> filterPredicate)
               where T : FrameworkElement
        {
            IParent parent = chain.GetSetting<T, IParent>("IParent");
            if (parent is ICanFilter)
            {
                ((ICanFilter)parent).FilterByText1And2And3<T>(chain, row, column, row2, column2, row3, column3, filterPredicate);
            }

            return chain;
        }

        #endregion
    }//end of class
}//end of namespace
